/*
 * car.c
 *
 *  Created on: 20/04/2011
 *      Author: Yotam and Gilad
 */

#include "car.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

#define NULL_ARGUMENT 0
#define ZERO 0

struct Car_t {
	int licensePlate;
	char* name;
	int price;
	int km;
	int salePrice;
	int saleKmMin;
	int saleKmMax;
	bool carInUse; // true if in use, false if not
};

//---------------------------Help Functions---------------------------------

static void carDestroy(Car car) {
	if ((car == NULL)) {
		return;
	}
	if (car->name != NULL) {
		free(car->name);
	}
	free(car);
	car = NULL;
}

//---------------------------Help Functions---------------------------------

Car carCreate(int licensePlate, const char* name, int price, int km) {
	//validity check
	assert(name!=NULL);
	if (name == NULL) {
		return NULL;
	}
	if (price <= ZERO) {
		return NULL;
	}
	if (km < ZERO) {
		return NULL;
	}
	// create the new car
	Car newCar = malloc(sizeof(struct Car_t));
	if (newCar == NULL) {
		return NULL;
	}
	newCar->licensePlate = licensePlate;
	newCar->name = malloc(strlen(name) + 1);
	if (newCar->name == NULL) {
		free(newCar);
		return NULL;
	}
	strcpy(newCar->name, name);
	newCar->price = price;
	newCar->km = km;
	newCar->salePrice = 0;
	newCar->saleKmMin = 0;
	newCar->saleKmMax = 0;
	newCar->carInUse = false;
	return newCar;
}

/**
 * carFilterNotInUse: checks the use status of a car. returns true if not in use
 *@param carElement - the car to check
 *return: true if not in use, false if in use.
 */
bool carFilterNotInUse(void* carElement) {
	Car car = (Car)carElement;
	return !(car->carInUse);
}

void carFree(void* carElement) {
	carDestroy((Car) carElement);
}

void* carCopy(void* carElement) {
	if (carElement == NULL) {
		return NULL;
	}
	Car actualCar = (Car) carElement;
	Car newCar = carCreate(actualCar->licensePlate, actualCar->name,
			actualCar->price, actualCar->km);
	newCar->salePrice = actualCar->salePrice;
	newCar->saleKmMin = actualCar->saleKmMin;
	newCar->saleKmMax = actualCar->saleKmMax;
	newCar->carInUse = actualCar->carInUse;
	if (newCar == NULL) {
		return NULL;
	}
	return newCar;
}

int carCompareByName(void* carElement1, void* carElement2) {
	return strcmp(((Car) carElement1)->name, ((Car) carElement2)->name);
}

int carCompareByKm(void* carElement1, void* carElement2) {
	return (((Car) carElement2)->km - ((Car) carElement1)->km);
}

int carCompareByLicensePlate(void* carElement1, void* carElement2) {
	return (((Car) carElement1)->licensePlate
			- ((Car) carElement2)->licensePlate);
}

int carGetLicensePlate(Car car) {
	assert(car != NULL);
	return car->licensePlate;
}

int carGetPrice(Car car) {
	assert(car != NULL);
	return car->price;
}

int carGetSalePrice(Car car) {
	assert(car != NULL);
	return car->salePrice;
}

char* carGetName(Car car) {
	assert(car != NULL);
	return car->name;
}

int carGetKm(Car car) {
	assert(car != NULL);
	return car->km;
}

int carGetSaleKmMin(Car car) {
	assert(car != NULL);
	return car->saleKmMin;
}

int carGetSaleKmMax(Car car) {
	assert(car != NULL);
	return car->saleKmMax;
}

bool carGetCarInUse(Car car) {
	assert(car != NULL);
	return car->carInUse;
}

CarResult carSale(Car car, int kmMin, int kmMax, int salePrice) {
	if ((kmMin < 1) || (kmMax < kmMin)) {
		return CAR_INVALID_KM;
	}
	if (salePrice <= ZERO) {
		return CAR_INVALID_PRICE;
	}
	if (car->carInUse == true) {
		return CAR_IN_USE;
	}
	if (carGetSaleStatus(car) == true) {
		return CAR_ALREADY_ON_SALE;
	}
	int regularPrice = (car->price) * (kmMin);
	if (salePrice >= regularPrice) {
		return CAR_SALE_PRICE_TOO_BIG;
	}
	car->salePrice = salePrice;
	car->saleKmMin = kmMin;
	car->saleKmMax = kmMax;
	return CAR_SUCCESS;
}

CarResult carNoSale(Car car) {
	if (car->carInUse == true) {
		return CAR_IN_USE;
	}
	if (car->salePrice == ZERO) {
		return CAR_NO_SALE;
	}
	car->salePrice = ZERO;
	car->saleKmMin = ZERO;
	car->saleKmMax = ZERO;
	return CAR_SUCCESS;
}

bool carGetSaleStatus(Car car) {
	if (car->salePrice > ZERO) {
		return true;
	}
	return false;
}

CarResult carSetUseMode(Car car, bool inUse) {
	if (car == NULL) {
		return CAR_NULL_ARGUMENT;
	}
	car->carInUse = inUse;
	return CAR_SUCCESS;
}

CarResult carUpdateKm(Car car, int addedKm) {
	if (car == NULL) {
		return CAR_NULL_ARGUMENT;
	}
	car->km += addedKm;
	return CAR_SUCCESS;
}
